﻿using AutoMapper;
using Furion;
using Furion.DependencyInjection;
using Furion.LinqBuilder;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using XinGuanERP.Db;
using XinGuanERP.Models;
using XinGuanERP.Models.Po;
using XinGuanERP.Models.Po.system;
using XinGuanERP.Models.Vo.system;
using XinGuanERP.Services.system.IServices;
using XinGuanERP.Utils;

namespace XinGuanERP.Services.system
{
    public class RoleService : IRoleService, ITransient
    {
        private readonly DefaultDbContext _defaultDbContext;

        public RoleService(DefaultDbContext defaultDbContext)
        {
            _defaultDbContext = defaultDbContext;
        }

        public int AssignMenu(string[] menuIds, string roleId)
        {
            // 删除角色和菜单关联
            _defaultDbContext.SysRoleMenus.RemoveRange(
                _defaultDbContext.SysRoleMenus.Where(t => t.RoleId == roleId).ToList());
            _defaultDbContext.SaveChanges();
            // 新增角色和菜单关联
            if (menuIds != null)
            {
                foreach (var item in menuIds)
                {
                    var sysRoleMenu = new SysRoleMenu()
                    {
                        Id = Guid.NewGuid().ToString().Replace("-", "").ToUpper(),
                        RoleId = roleId,
                        MenuId = item
                    };
                    _defaultDbContext.SysRoleMenus.Add(sysRoleMenu);
                }
            }
            return _defaultDbContext.SaveChanges();
        }

        public bool DeleteRole(string Id)
        {
            var res = _defaultDbContext.Roles.Where(t => t.Id == Id).FirstOrDefault();
            if (res != null)
            {
                _defaultDbContext.Roles.Remove(res);
                return _defaultDbContext.SaveChanges() > 0;
            }
            else
            {
                return false;
            }
        }

        public List<RoleVo> GetRoleWithList(string? roleName, string? status)
        {
            var res = new List<Role>();
            if (!roleName.IsNullOrEmpty() && status.IsNullOrEmpty())
            {
                res = _defaultDbContext.Roles
                    .Where(t => EF.Functions.Like(t.RoleName, "%" + roleName + "%"))
                    .OrderBy(t => t.OrderNo).ToList();
            }

            if (!status.IsNullOrEmpty() && roleName.IsNullOrEmpty())
            {
                res = _defaultDbContext.Roles
                    .Where(t => EF.Functions.Like(t.Status, "%" + status + "%"))
                    .OrderBy(t => t.OrderNo).ToList();
            }

            if (!roleName.IsNullOrEmpty() && !status.IsNullOrEmpty())
            {
                res = _defaultDbContext.Roles
                    .Where(t => EF.Functions.Like(t.RoleName, "%" + roleName + "%"))
                    .Where(t => EF.Functions.Like(t.Status, "%" + status + "%"))
                    .OrderBy(t => t.OrderNo).ToList();
            }

            if (roleName.IsNullOrEmpty() && status.IsNullOrEmpty())
            {
                res = _defaultDbContext.Roles.OrderBy(t => t.OrderNo).ToList();
            }


            List<RoleVo> viewRoles = new List<RoleVo>();
            var config = new MapperConfiguration(cfg => cfg.CreateMap<Role, RoleVo>());
            var mapper = config.CreateMapper();
            foreach (var role in res)
            {
                viewRoles.Add(mapper.Map<RoleVo>(role));
            }
            return viewRoles;
        }

        public PageResult<RoleVo> GetRoleWithPage(int page, int pageSize, string? roleName, string? status)
        {
            var res = new List<Role>();
            var count = 0;
            var sql = _defaultDbContext.Roles
                .OrderBy(t => t.OrderNo).AsQueryable();
            if (!roleName.IsNullOrEmpty() && status.IsNullOrEmpty())
            {
                res = sql.Where(t =>
                        EF.Functions.Like(t.RoleName, "%" + roleName + "%"))
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Where(t =>
                        EF.Functions.Like(t.RoleName, "%" + roleName + "%"))
                    .Count();
            }

            if (!status.IsNullOrEmpty() && roleName.IsNullOrEmpty())
            {
                res = sql.Where(t =>
                        EF.Functions.Like(t.Status, "%" + status + "%"))
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Where(t =>
                        EF.Functions.Like(t.Status, "%" + status + "%"))
                    .Count();
            }

            if (!roleName.IsNullOrEmpty() && !status.IsNullOrEmpty())
            {
                res = sql.Where(t => EF.Functions.Like(t.RoleName, "%" + roleName + "%"))
                    .Where(t => EF.Functions.Like(t.Status, "%" + status + "%"))
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Where(t => EF.Functions.Like(t.RoleName, "%" + roleName + "%"))
                    .Where(t => EF.Functions.Like(t.Status, "%" + status + "%"))
                    .Count();
            }

            if (roleName.IsNullOrEmpty() && status.IsNullOrEmpty())
            {
                res = sql.Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count();
            }


            List<RoleVo> viewRoles = new List<RoleVo>();
            var config = new MapperConfiguration(cfg => cfg.CreateMap<Role, RoleVo>());
            var mapper = config.CreateMapper();
            foreach (var role in res)
            {
                viewRoles.Add(mapper.Map<RoleVo>(role));
            }
            return new PageResult<RoleVo>()
            {
                Items = viewRoles,
                Total = count
            };
        }

        public List<SysMenuVo> GetSysMenuByRoleIdWithOptionTree(string roleId)
        {
            var sysRoleMenuList = _defaultDbContext.SysRoleMenus.Where(t => t.RoleId == roleId).ToList();
            var sysMenuList = sysRoleMenuList.Select(t =>
            {
                return _defaultDbContext.SysMenus.Where(m => m.Id == t.MenuId).FirstOrDefault();
            }).ToList();
            var sysMenuListWithOptionTree = new List<SysMenuVo>();
            var config = new MapperConfiguration(cfg => cfg.CreateMap<SysMenu, SysMenuVo>());
            var mapper = config.CreateMapper();
            foreach (var sysMenu in sysMenuList)
            {
                sysMenuListWithOptionTree.Add(mapper.Map<SysMenuVo>(sysMenu));
            }
            return sysMenuListWithOptionTree;
        }

        public bool SetRoleStatus(string Id, string Status)
        {
            var res = _defaultDbContext.Roles.FirstOrDefault(t => t.Id == Id);
            if (res == null)
            {
                return false;
            }
            else
            {
                res.Status = Status;
                res.UpdateTime = DateTime.Now;
                res.UpdateUserId = App.User?.FindFirstValue("UserId");
                res.UpdateUserName = App.User?.FindFirstValue("UserName");
            }
            return _defaultDbContext.SaveChanges() > 0;
        }

        public bool UpdateRole(RoleVo viewRole)
        {
            var res = _defaultDbContext.Roles.FirstOrDefault(x => x.Id == viewRole.Id);
            var config = new MapperConfiguration(cfg => cfg.CreateMap<RoleVo, Role>()
                .BeforeMap((src, des) => src.Id = Guid.NewGuid().ToString().Replace("-", "").ToUpper())
                .BeforeMap((src, des) => des.CreateTime = DateTime.Now)
                .BeforeMap((src, des) => des.CreateUserId = App.User?.FindFirstValue("UserId"))
                .BeforeMap((src, des) => des.CreateUserName = App.User?.FindFirstValue("UserName")));
            var mapper = config.CreateMapper();
            if (res == null)
            {
                _defaultDbContext.Roles.Add(
                    mapper.Map<Role>(viewRole)
                );
            }
            else
            {
                res = new MapperConfiguration(cfg => cfg.CreateMap<RoleVo, Role>()
                    .BeforeMap((src, des) => des.UpdateTime = DateTime.Now)
                    .BeforeMap((src, des) => des.UpdateUserId = App.User?.FindFirstValue("UserId"))
                    .BeforeMap((src, des) => des.UpdateUserName = App.User?.FindFirstValue("UserName")))
                    .CreateMapper().Map(viewRole, res);
            }
            return _defaultDbContext.SaveChanges() > 0;
        }
    }
}
